Problem:
Score : 200 points

Problem Statement

You are visiting a large electronics store to buy a refrigerator and a microwave.

The store sells A kinds of refrigerators and B kinds of microwaves. The i-th refrigerator ( 1 \le i \le A ) is sold at a_i yen (the currency of Japan), and the j-th microwave ( 1 \le j \le B ) is sold at b_j yen.

You have M discount tickets. With the i-th ticket ( 1 \le i \le M ), you can get a discount of c_i yen from the total price when buying the x_i-th refrigerator and the y_i-th microwave together. Only one ticket can be used at a time.

You are planning to buy one refrigerator and one microwave. Find the minimum amount of money required.

Constraints

All values in input are integers.

1 \le A \le 10^5

1 \le B \le 10^5

1 \le M \le 10^5

1 \le a_i , b_i , c_i \le 10^5

1 \le x_i \le A

1 \le y_i \le B

c_i \le a_{x_i} + b_{y_i}

Input

Input is given from Standard Input in the following format:

A B M
a_1 a_2 ... a_A
b_1 b_2 ... b_B
x_1 y_1 c_1
\vdots
x_M y_M c_M

Output

Print the answer.

Sample Input 1

2 3 1
3 3
3 3 3
1 2 1

Sample Output 1

5

With the ticket, you can get the 1-st refrigerator and the 2-nd microwave for 3+3-1=5 yen.

Sample Input 2

1 1 2
10
10
1 1 5
1 1 10

Sample Output 2

10

Note that you cannot use more than one ticket at a time.

Sample Input 3

2 2 1
3 5
3 5
2 2 2

Sample Output 3

6

You can get the 1-st refrigerator and the 1-st microwave for 6 yen, which is the minimum amount to pay in this case.
Note that using a ticket is optional.

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

import java.util.*;
import java.io.*;


public class Main{
    public static void main(String[] args) {
        FastScanner sc = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);
        int A = sc.nextInt();
        int B = sc.nextInt();
        int M  =sc.nextInt();
        int[] a = new int[A];
        int[] b = new int[B];
        int[] res = new int[M];
        int minA = Integer.MAX_VALUE, minB = Integer.MAX_VALUE;
        for(int i=0;i<A;i++){
            a[i] = sc.nextInt();
            minA = Math.min(a[i], minA);
        }
        for(int i=0;i<B;i++){
            b[i] = sc.nextInt();
            minB = Math.min(b[i], minB);
        }
        for(int i=0;i<M;i++){
            res[i] = a[sc.nextInt()-1] + b[sc.nextInt()-1] - sc.nextInt();
        }
        Arrays.sort(res);
        out.println(Math.min(res[0], minA + minB));


        out.flush();
    }

}

class BinaryIndexedTree{
    int[] data;
    int[] tree;
    int n;

    public BinaryIndexedTree(int[] data){
        this.data = data;
        this.n = data.length;
        this.tree = new int[n+1];
        buildTree();
    }

    public void buildTree(){
        for(int i=0;i<n;i++){
            add(i+1, data[i]);
        }
    }

    public void add(int index, int value){
        for(int i=index; i<=n; i+=i & -i){
            tree[i] += value;
        }
    }

    public int sum(int from, int to){
        return sum(to) - sum(from-1);
    }

    public int sum(int index){
        int sum = 0;
        for(int i=index; i>0; i-=i & -i){
            sum += tree[i];
        }
        return sum;
    }
}

class nextPermutation{
    public static int[] swap(int data[], int left, int right)
    {

        // Swap the data
        int temp = data[left];
        data[left] = data[right];
        data[right] = temp;

        // Return the updated array
        return data;
    }

    // Function to reverse the sub-array
    // starting from left to the right
    // both inclusive
    public static int[] reverse(int data[], int left, int right)
    {

        // Reverse the sub-array
        while (left < right) {
            int temp = data[left];
            data[left++] = data[right];
            data[right--] = temp;
        }

        // Return the updated array
        return data;
    }

    // Function to find the next permutation
    // of the given integer array
    public static boolean findNextPermutation(int data[])
    {

        // If the given dataset is empty
        // or contains only one element
        // next_permutation is not possible
        if (data.length <= 1)
            return false;

        int last = data.length - 2;

        // find the longest non-increasing suffix
        // and find the pivot
        while (last >= 0) {
            if (data[last] < data[last + 1]) {
                break;
            }
            last--;
        }

        // If there is no increasing pair
        // there is no higher order permutation
        if (last < 0)
            return false;

        int nextGreater = data.length - 1;

        // Find the rightmost successor to the pivot
        for (int i = data.length - 1; i > last; i--) {
            if (data[i] > data[last]) {
                nextGreater = i;
                break;
            }
        }

        // Swap the successor and the pivot
        data = swap(data, nextGreater, last);

        // Reverse the suffix
        data = reverse(data, last + 1, data.length - 1);

        // Return true as the next_permutation is done
        return true;
    }
}

class graph{
    int[][] graph;
    public graph(int[][] graph){
        this.graph = graph;
    }

    public long dijkstra(int s, int t){
        Integer[] dist = new Integer[graph.length];
        int[] prev = new int[graph.length];
        Arrays.fill(prev, -1);
        PriorityQueue<Integer> manage = new PriorityQueue<>((x,y) -> dist[x]-dist[y]);
        HashSet<Integer> searched = new HashSet<>();
        Arrays.fill(dist,Integer.MAX_VALUE);
        dist[s] = 0;
        searched.add(s);
        for(int i=0;i<graph.length;i++){
            if(graph[s][i]!=Integer.MAX_VALUE){
                dist[i] = graph[s][i];
                prev[i] = s;
                manage.add(i);
            }
        }
        while(manage.size()>0){
            int now = manage.poll();
            searched.add(now);
            for(int i=0;i<graph.length;i++){
                if(graph[now][i]!=Integer.MAX_VALUE){
                    if(!searched.contains(i)){
                        if(dist[i]==Integer.MAX_VALUE){
                            dist[i] = dist[now] + graph[now][i];
                            prev[i] = now;
                            manage.add(i);
                        }
                        else{
                            dist[i] = Math.min(dist[i],dist[now]+graph[now][i]);
                            if(dist[i]==dist[now]+graph[now][i]) prev[i] = now;
                            manage.remove(i);
                            manage.add(i);
                        }
                    }
                }
            }
            if(searched.contains(t)) break;
        }

        return dist[t];
    }

    public boolean judgeBipartitegraph(){
        int[] color = new int[graph.length];
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        HashSet<Integer> visited = new HashSet<>();
        queue.add(0);
        color[0] = 1;
        while(queue.size()>0){
            int now = queue.poll();
            visited.add(now);
            for(int j=0;j<graph[now].length;j++){
                if(visited.contains(j)) continue;
                if(graph[now][j]!=0){
                    if(color[j]==color[now]) return false;
                    queue.add(j);
                    if(color[j]==0) color[j] = -1*color[now];
                }
            }
        }
        return true;
    }

    public int[][] prim(){
        int[] mincost = new int[graph.length];
        boolean[] used = new boolean[graph.length];
        int[][] spanning = new int[graph.length][graph.length];
        for(int i=0;i<graph.length;i++){
            mincost[i] = Integer.MAX_VALUE;
            used[i] = false;
        }
        mincost[0] = 0;
        int totalCost = 0;
        while(true){
            int v = -1;
            for(int u=0;u<graph.length;u++){
                if(!used[u] && (v==-1||mincost[u]<mincost[v])){
                    v = u;
                }
            }
            if(v==-1) break;
            used[v] = true;
            totalCost += mincost[v];
            for(int u=0;u<graph.length;u++){
                if(graph[v][u]<mincost[u]){
                    mincost[u] = graph[v][u];
                }
            }
            for(int u=0;u<graph.length;u++){
                if(mincost[u]==graph[v][u]){
                    spanning[v][u] = 1;
                    spanning[u][v] = 1;
                    break;
                }
            }
        }
        return spanning;
        // return totalCost;
    }

    public int[][] wf(){
        int[][] dist = new int[graph.length][graph.length];
        dist = graph.clone();
        // for(int i=0;i<graph.length;i++){
        //     dist[i][i] = 0;
        // }
        for(int k=0;k<graph.length;k++){
            for(int i=0;i<graph.length;i++){
                for(int j=0;j<graph.length;j++){
                    if(dist[i][k]==Integer.MAX_VALUE || dist[k][j]==Integer.MAX_VALUE) continue;

                    dist[i][j] = Math.min(dist[i][j],dist[i][k]+dist[k][j]);

                }
            }
        }
        for(int i=0;i<graph.length;i++){
            if(dist[i][i]<0) return null;
        }
        return dist;
    }
}

class FastScanner {
    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return minus ? -n : n;
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
        return (int) nl;
    }
    public double nextDouble() { return Double.parseDouble(next());}
}